package app_log

import (
	"fmt"
	"runtime"
	"strconv"
)

const (
	bBlack  = 40
	bRed    = 41
	bGreen  = 42
	bYellow = 43
	bBlue   = 44
	bPurple = 45
	bCyan   = 46
	bWhite  = 47

	fBlack  = 30
	fRed    = 31
	fGreen  = 32
	fYellow = 33
	fBlue   = 34
	fPurple = 35
	fCyan   = 36
	fWhite  = 37

	mDefault   = 0
	mHighlight = 1
	mUnderline = 4
	mBlink     = 5
	mInvert    = 7
	mHide      = 8
)

type ColorString struct {
	OriginStr   string
	completeStr []*ColorString

	mod        int
	background int
	foreground int
}

func NewColorString(str string) *ColorString {
	return &ColorString{OriginStr: str}
}

func (c *ColorString) Append(str string) *ColorString {

	c.completeStr = append(c.completeStr, c)
	c.OriginStr = str
	c.mod = 0
	c.background = 0
	c.foreground = 0
	return c
}

func (c *ColorString) toStringWithColor(withColor bool) string {
	if !withColor {
		return c.OriginStr
	}
	if runtime.GOOS == "windows" {
		return c.OriginStr
	} else {

		var foregroundStr = ""
		if c.foreground != 0 {
			foregroundStr = strconv.Itoa(c.foreground)
		}
		var backgroundStr = ""
		if c.background != 0 {
			backgroundStr = strconv.Itoa(c.background)
		}
		return fmt.Sprintf("%c[%d;%s;%sm%s%c[0m", 0x1B, c.mod, backgroundStr, foregroundStr, c.OriginStr, 0x1B)
	}
}

func (c *ColorString) Str() string {
	var str = ""
	for _, item := range c.completeStr {
		str += item.toStringWithColor(true)
	}
	return str + c.toStringWithColor(true)
}

func (c *ColorString) NoColorStr() string {
	var str = ""
	for _, item := range c.completeStr {
		str += item.toStringWithColor(false)
	}
	return str + c.toStringWithColor(false)
}

func (c *ColorString) OnBlack() *ColorString {
	c.background = bBlack
	return c
}
func (c *ColorString) OnRed() *ColorString {
	c.background = bRed
	return c
}
func (c *ColorString) OnGreen() *ColorString {
	c.background = bGreen
	return c
}
func (c *ColorString) OnYellow() *ColorString {
	c.background = bYellow
	return c
}
func (c *ColorString) OnBlue() *ColorString {
	c.background = bBlue
	return c
}
func (c *ColorString) OnPurple() *ColorString {
	c.background = bPurple
	return c
}
func (c *ColorString) OnCyan() *ColorString {
	c.background = bCyan
	return c
}
func (c *ColorString) OnWhite() *ColorString {
	c.background = bWhite
	return c
}

func (c *ColorString) Black() *ColorString {
	c.foreground = fBlack
	return c
}
func (c *ColorString) Red() *ColorString {
	c.foreground = fRed
	return c
}
func (c *ColorString) Green() *ColorString {
	c.foreground = fGreen
	return c
}
func (c *ColorString) Yellow() *ColorString {
	c.foreground = fYellow
	return c
}
func (c *ColorString) Blue() *ColorString {
	c.foreground = fBlue
	return c
}
func (c *ColorString) Purple() *ColorString {
	c.foreground = fPurple
	return c
}
func (c *ColorString) Cyan() *ColorString {
	c.foreground = fCyan
	return c
}
func (c *ColorString) White() *ColorString {
	c.foreground = fWhite
	return c
}

func (c *ColorString) defaultType() *ColorString {
	c.mod = mDefault
	return c
}

func (c *ColorString) Highlight() *ColorString {
	c.mod = mHighlight
	return c
}

func (c *ColorString) Underline() *ColorString {
	c.mod = mUnderline
	return c
}

func (c *ColorString) Blink() *ColorString {
	c.mod = mBlink
	return c
}

func (c *ColorString) Invert() *ColorString {
	c.mod = mInvert
	return c
}

func (c *ColorString) Hide() *ColorString {
	c.mod = mHide
	return c
}
